package com.satan.juc.demo15;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/*
在这个例子中，我们创建了一个ConcurrentLinkedQueue实例，并且有多个生产者和消费者线程。
生产者线程负责向队列中添加元素，而消费者线程负责从队列中取出元素。
由于ConcurrentLinkedQueue是线程安全的，所以即使在多线程环境下，也不需要额外的同步措施。
*/
public class ConcurrentQueueExample {
    private static final ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();

    public static void main(String[] args) throws InterruptedException {
        // 创建一个固定大小的线程池来模拟高并发环境
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        // 模拟多个生产者线程向队列中添加元素
        for (int i = 0; i < 5; i++) {
            executorService.submit(new Producer("Producer" + i, queue));
        }

        // 模拟多个消费者线程从队列中取出元素
        for (int i = 0; i < 5; i++) {
            executorService.submit(new Consumer("Consumer" + i, queue));
        }

        // 模拟运行一段时间后关闭线程池
        executorService.awaitTermination(2, TimeUnit.SECONDS);
        executorService.shutdownNow();
    }

    static class Producer implements Runnable {
        private final String name;
        private final ConcurrentLinkedQueue<String> queue;

        Producer(String name, ConcurrentLinkedQueue<String> queue) {
            this.name = name;
            this.queue = queue;
        }

        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                queue.offer(name + " element " + i);
                System.out.println(name + " produced element " + i);
            }
        }
    }

    static class Consumer implements Runnable {
        private final String name;
        private final ConcurrentLinkedQueue<String> queue;

        Consumer(String name, ConcurrentLinkedQueue<String> queue) {
            this.name = name;
            this.queue = queue;
        }

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                String element = queue.poll();
                if (element != null) {
                    System.out.println(name + " consumed " + element);
                }
            }
        }
    }
}
